package storage

import (
	"fmt"
	"gitee.com/igolang/imoney/internal/common/constants"
	"gitee.com/igolang/pkg/xcfg"
	"gitee.com/igolang/pkg/xutils"
	"github.com/pkg/errors"
	"io"
	"mime/multipart"
	"os"
	"path/filepath"
	"strings"
	"time"
)

type localStorage struct {
}

func (f *localStorage) Get(name string) (string, error) {
	basePath := f.BasePath()
	if basePath == "" {
		return "", errors.New("file base path nil")
	}

	filename := filepath.Join(f.BasePath(), name)
	if !xutils.FileExists(filename) {
		return "", errors.New("file not exists")
	}
	return filename, nil
}

func (f *localStorage) Save(file *multipart.FileHeader) (*FileInfo, error) {
	// 开始处理
	var err error
	// 准备保存地址
	basePath := f.BasePath()
	if basePath == "" {
		return nil, errors.New("file base path nil")
	}
	savePath := filepath.Join(basePath, f.FilePath())
	// 处理文件
	newName := f.filename(file.Filename)
	filename := filepath.Join(savePath, newName)
	if err = f.SaveUploadedFile(file, filename); err != nil {
		return nil, f.Err(err)
	}
	profileName := strings.ReplaceAll(filename, strings.TrimRight(f.BasePath(), "/"), constants.ProFilePath)
	info := &FileInfo{
		FileName:     profileName,
		OriginalName: file.Filename,
		NewName:      newName,
		Url:          profileName,
	}
	return info, nil
}

// SaveUploadedFile uploads the form file to specific dst.
func (f *localStorage) SaveUploadedFile(file *multipart.FileHeader, dst string) error {
	src, err := file.Open()
	if err != nil {
		return err
	}
	defer src.Close()

	if err = os.MkdirAll(filepath.Dir(dst), 0750); err != nil {
		return err
	}

	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer out.Close()

	_, err = io.Copy(out, src)
	return err
}

func (f *localStorage) filename(name string) string {
	n := strings.LastIndex(name, ".")
	if n == -1 {
		return fmt.Sprintf("%s_UPLOAD%d", name, time.Now().UnixNano())
	}

	return fmt.Sprintf("%s_UPLOAD%d%s", name[:n], time.Now().UnixNano(), name[n:])
}

func (f *localStorage) BasePath() string {
	basePath := xcfg.GetString("storage.local.path")
	if basePath == "" {
		return ""
	}
	// 判断是否是绝对路径
	if !filepath.IsAbs(basePath) {
		// 获取当前运行目录
		basePath = filepath.Join(xutils.CurrentAbPath(), basePath)
	}

	return basePath
}

func (f *localStorage) FilePath() string {
	return time.Now().Format("06/01/02")
}

func (f *localStorage) Err(err any) error {
	e := errors.Errorf("uploadFileErr: %v", err)
	log.Println(e)
	return e
}

func (f *localStorage) Printf(format string, v ...any) {
	log.Printf("uploadFileDebug: "+format, v...)
}
